<!DOCTYPE html>
<html lang="zh-cmn-Hans">

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no" />
        <title>无 form 表单验证</title>
        <link rel="stylesheet" href="bootstrap.css" />
        <script src="../dist/validator.js"></script>
        <style>

        .jumbotron {
            background: #61b2a7 url(bg.png) 0 50%;
            border-bottom: 1px solid rgba(34,34,34,0.2);
            box-shadow: inset 0 10px 10px #61b2a7;
        }

        .jumbotron .title, .jumbotron a {
            color: white;
            text-shadow: 1px 1px 2px rgba(34,34,34,0.5);
        }

        .valid-error {
            border-color: #a94442;
            color: #a94442;
            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
            box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
        }

        .valid-error:focus {
            border-color: #843534;
            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
            box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;
        }

        .valid-error-message {
            display: block;
            margin: 5px 0;
            font-style: normal;
            color: #a94442;
        }

        .valid-success {
            border-color: #3c763d;
            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
            box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
        }

        .valid-success:focus {
            border-color: #2b542c;
            -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
            box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;
        }

        </style>
    </head>

    <body>


        <div class="container">

            <h3>无 form 表单验证</h3>

            <div class="form-group">
                <label for="email">邮箱：</label>
                <input class="form-control" id="email" name="email" type="email" placeholder="请输入邮箱" />
            </div>

            <div class="form-group">
                <button class="btn btn-default" id="setErrorEmail" type="button">设置错误邮箱</button> 
                <button class="btn btn-default" id="setRightEmail" type="button">设置正确邮箱</button> 
                <button class="btn btn-info" id="validEmail" type="button">验证邮箱</button>
            </div>

            <div class="form-group">
                <label for="phone">手机：</label>
                <input class="form-control" id="phone" name="phone" type="text" placeholder="请输入手机号" />
            </div>

            <div class="form-group">
                <label for="birthday">生日：</label>
                <input class="form-control" id="birthday" name="birthday" type="text" placeholder="请填写生日">
            </div>

            <div class="form-group">
                <label>性别：</label>
                <div class="radio">
                    <label>
                        <input id="male" type="radio" name="sex" value="0" /> 男
                    </label>
                    <label>
                        <input id="female" type="radio" name="sex" value="1" /> 女
                    </label>
                </div>
            </div>

            <div class="form-group">
                <label for="city">城市：</label>
                <select class="form-control" id="city" name="city">
                    <option value="">请选择</option>
                    <option value="0">北京</option>
                    <option value="1">上海</option>
                    <option value="2">重庆</option>
                    <option value="3">成都</option>
                </select>
            </div>

            <div class="form-group">
                <label>爱好：</label>
                <div class="checkbox">
                    <label>
                        <input id="badminton" name="hobby" type="checkbox" value="1" /> 羽毛球
                    </label>
                    <label>
                        <input id="swim" name="hobby" type="checkbox" value="2" /> 游泳
                    </label>
                    <label>
                        <input id="run" name="hobby" type="checkbox" value="3" /> 跑步
                    </label>
                </div>
            </div>

            <div class="form-group">
                <label for="remarks">简介：</label>
                <textarea class="form-control" id="remarks" name="remarks" rows="3" placeholder="一句话描述自己"></textarea>
            </div>

            <input class="btn btn-primary" id="submit" type="button" value="提交" />

            <h3>序列化错误类</h3>

            <pre id="validate_result"></pre>

        </div>

        <script>
            var validator = new Validator({
                fields: {
                    email: {
                        rules: 'required | is_email | max_length(32)',
                        messages: "不能为空 | 请输入合法邮箱 | 不能超过 {{param}} 个字符"
                    },
                    phone: {
                        rules: 'is_phone',
                        messages: "手机号： {{value}} 不合法"
                    },
                    birthday: {
                        rules: 'required | is_date',
                        messages: "不能为空 | 请输入合法日期"
                    },
                    sex: {
                        rules: 'required',
                        messages: "不能为空"
                    },
                    city: {
                        rules: 'required',
                        messages: "不能为空"
                    },
                    hobby: {
                        rules: 'required | select_limit(2)',
                        messages: "不能为空 | 至少选择两项"
                    },
                    remarks: {
                        rules: 'min_length(10) | max_length(60)',
                        messages: "不能少于 {{param}} 个字符 | 不能超过 {{param}} 个字符"
                    }
                },
                // 参数：errorEl 错误信息节点，fieldEl 出现错误的表单节点
                errorPlacement: function(errorEl, fieldEl) {
                    // 非 label 、radio 元素
                    if (!isRadioOrCheckbox(fieldEl)) {
                        fieldEl.parentNode.appendChild(errorEl);
                    } else {
                        fieldEl.parentNode.parentNode.parentNode.appendChild(errorEl);
                    }
                },
                callback: function(errors, event) {

                    var submitButton = document.getElementById('submit');
                    removeClass(submitButton, 'btn-primary');
                    // 如果错误为空
                    if (!errors) {
                        // 演示阻止表单提交
                        validator.preventSubmit();
                        // 设置成功按钮样式
                        removeClass(submitButton, 'btn-danger');
                        addClass(submitButton, 'btn-success');
                        submitButton.value = '验证成功';
                    } else {
                        // 设置错误按钮样式
                        removeClass(submitButton, 'btn-success');
                        addClass(submitButton, 'btn-danger');
                        submitButton.value = '验证失败';
                        
                    }
                    // 结果显示
                    document.getElementById('validate_result').innerHTML = JSON.stringify(errors);

                }
            });

            // checkbox 至少选择两项
            // 扩展内部验证方法 field: 验证域， param: 参数 如 select_limit(2)
            validator.addMethod('select_limit', function(field, param) {
                // checkbox 至少选择两项
                var checkedNum = 0;
                for (var i = 0, elLength = field.el.length; i < elLength; i++) {
                    if (field.el[i].checked) {
                        checkedNum += 1;
                    }
                }
                return checkedNum >= param;
            });

            // 绑定表单改变事件
            validator.onInputEvent('email', 'all').onInputEvent('phone', 'change');

            // 点击验证
            document.getElementById('submit').onclick = function() {
                validator.validate();
            }

            // 设置邮箱值
            var emailEL = document.getElementById('email');

            var setErrorEmail = document.getElementById('setErrorEmail');
            addEvent(setErrorEmail, 'click', function() {
                emailEL.value = 'anonymous#qq.com';
            });

            var setRightEmail = document.getElementById('setRightEmail');
            addEvent(setRightEmail, 'click', function() {
                emailEL.value = 'anonymous@qq.com';
            });

            // 验证邮箱值
            var validEmailButton = document.getElementById('validEmail');
            addEvent(validEmailButton, 'click', function() {
                // 通过 name 验证单个表单域
                validator.validateByName('email');
            });

            // Demo 中未使用 jQuery 类库，作为演示添加方法

            /**
             * 判断节点是否为 radio 或者 checkbox
             * @param {Element} 传入节点
             * @return {Boolean}
             */
            function isRadioOrCheckbox(el) {
                return el.type === 'radio' || el.type === 'checkbox';
            }

            /**
             * 判断是否包含 class
             */
            function hasClass(el, cls) {
                return el.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
            }

            /**
             * 添加 class
             */
            function addClass(el, cls) {
                if (!hasClass(el, cls)) {
                    el.classList ? el.classList.add(cls) : el.className += ' ' + cls;
                }
            }

            /**
             * 移除 class
             */
            function removeClass(el, cls) {
                if (hasClass(el, cls)) {
                    var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
                    el.classList ? el.classList.remove(cls) : el.className = el.className.replace(reg, ' ');
                }
            }

            /**
             * 添加事件
             */
            function addEvent(el, type, fn) {
                if (typeof el.addEventListener != 'undefined') {
                    el.addEventListener(type, fn, false);
                } else if (typeof el.attachEvent != 'undefined') {
                    el.attachEvent('on' + type, fn);
                } else {
                    el['on' + type] = fn;
                };
            }

        </script>
    </body>

</html>